<template>
  <el-dialog
    v-model="dialogVisible"
    v-bind="dialogProps"
    :title="title"
    :width="width"
    :fullscreen="fullscreen"
    :top="top"
    :modal="modal"
    :modal-class="modalClass"
    :append-to-body="appendToBody"
    :append-to="appendTo"
    :lock-scroll="lockScroll"
    :close-on-click-modal="closeOnClickModal"
    :close-on-press-escape="closeOnPressEscape"
    :show-close="showClose"
    :before-close="beforeClose"
    :center="center"
    :align-center="alignCenter"
    :destroy-on-close="destroyOnClose"
    :close-icon="closeIcon"
    :custom-class="customClass"
    @open="handleOpen"
    @close="handleClose"
    @opened="handleOpened"
    @closed="handleClosed"
  >
    <div class="dialog-content" :class="{ 'is-loading': loading }">
      <div v-if="loading" class="dialog-loading">
        <el-icon class="is-loading"><Loading /></el-icon>
        <span>加载中...</span>
      </div>
      <slot v-else></slot>
    </div>
    
    <template #footer v-if="showFooter">
      <slot name="footer">
        <div class="dialog-footer">
          <el-button @click="handleCancel">{{ cancelText }}</el-button>
          <el-button type="primary" @click="handleConfirm" :loading="confirmLoading">
            {{ confirmText }}
          </el-button>
        </div>
      </slot>
    </template>
  </el-dialog>
</template>

<script setup>
import { ref, computed, watch } from 'vue'

const props = defineProps({
  // 对话框是否显示
  modelValue: {
    type: Boolean,
    default: false
  },
  // 对话框标题
  title: {
    type: String,
    default: ''
  },
  // 对话框宽度
  width: {
    type: [String, Number],
    default: '50%'
  },
  // 是否为全屏对话框
  fullscreen: {
    type: Boolean,
    default: false
  },
  // Dialog CSS 中的 margin-top 值
  top: {
    type: String,
    default: '15vh'
  },
  // 是否需要遮罩层
  modal: {
    type: Boolean,
    default: true
  },
  // 遮罩层的自定义类名
  modalClass: {
    type: String,
    default: ''
  },
  // Dialog 自身是否插入至 body 元素上
  appendToBody: {
    type: Boolean,
    default: false
  },
  // Dialog 挂载到哪个 DOM 元素
  appendTo: {
    type: [String, Object],
    default: ''
  },
  // 是否在 Dialog 出现时将 body 滚动锁定
  lockScroll: {
    type: Boolean,
    default: true
  },
  // 是否可以通过点击 modal 关闭 Dialog
  closeOnClickModal: {
    type: Boolean,
    default: false
  },
  // 是否可以通过按下 ESC 关闭 Dialog
  closeOnPressEscape: {
    type: Boolean,
    default: true
  },
  // 是否显示关闭按钮
  showClose: {
    type: Boolean,
    default: true
  },
  // 关闭前的回调，会暂停 Dialog 的关闭
  beforeClose: {
    type: Function,
    default: null
  },
  // 是否让 Dialog 的头部和底部居中排列
  center: {
    type: Boolean,
    default: false
  },
  // 是否水平垂直对齐对话框
  alignCenter: {
    type: Boolean,
    default: false
  },
  // 关闭时是否销毁 Dialog 中的元素
  destroyOnClose: {
    type: Boolean,
    default: false
  },
  // 自定义关闭图标
  closeIcon: {
    type: String,
    default: ''
  },
  // Dialog 的自定义类名
  customClass: {
    type: String,
    default: ''
  },
  // 是否显示底部
  showFooter: {
    type: Boolean,
    default: true
  },
  // 取消按钮文本
  cancelText: {
    type: String,
    default: '取消'
  },
  // 确认按钮文本
  confirmText: {
    type: String,
    default: '确认'
  },
  // 确认按钮是否加载中
  confirmLoading: {
    type: Boolean,
    default: false
  },
  // 内容是否加载中
  loading: {
    type: Boolean,
    default: false
  }
})

const emit = defineEmits([
  'update:modelValue',
  'open',
  'close',
  'opened',
  'closed',
  'cancel',
  'confirm'
])

// 对话框显示状态
const dialogVisible = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value)
})

// 对话框属性
const dialogProps = computed(() => {
  const {
    fullscreen,
    top,
    modal,
    modalClass,
    appendToBody,
    appendTo,
    lockScroll,
    closeOnClickModal,
    closeOnPressEscape,
    showClose,
    beforeClose,
    center,
    alignCenter,
    destroyOnClose,
    closeIcon,
    customClass
  } = props
  
  return {
    fullscreen,
    top,
    modal,
    modalClass,
    appendToBody,
    appendTo,
    lockScroll,
    closeOnClickModal,
    closeOnPressEscape,
    showClose,
    beforeClose,
    center,
    alignCenter,
    destroyOnClose,
    closeIcon,
    customClass
  }
})

// 处理对话框打开
const handleOpen = () => {
  emit('open')
}

// 处理对话框关闭
const handleClose = () => {
  emit('close')
}

// 处理对话框打开动画结束
const handleOpened = () => {
  emit('opened')
}

// 处理对话框关闭动画结束
const handleClosed = () => {
  emit('closed')
}

// 处理取消按钮点击
const handleCancel = () => {
  emit('cancel')
  dialogVisible.value = false
}

// 处理确认按钮点击
const handleConfirm = () => {
  emit('confirm')
}

// 暴露方法给父组件
defineExpose({
  open: () => {
    dialogVisible.value = true
  },
  close: () => {
    dialogVisible.value = false
  }
})
</script>

<style lang="scss" scoped>
.dialog-content {
  position: relative;
  min-height: 100px;
  
  &.is-loading {
    min-height: 200px;
  }
  
  .dialog-loading {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    background: rgba(255, 255, 255, 0.7);
    color: var(--el-text-color-secondary);
    
    .el-icon {
      font-size: 24px;
      margin-bottom: 8px;
    }
  }
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

:deep(.el-dialog) {
  border-radius: var(--el-border-radius-base);
  
  .el-dialog__header {
    padding: 20px 20px 10px;
    border-bottom: 1px solid var(--el-border-color-lighter);
    
    .el-dialog__title {
      font-size: 18px;
      font-weight: 500;
    }
  }
  
  .el-dialog__body {
    padding: 20px;
  }
  
  .el-dialog__footer {
    padding: 10px 20px 20px;
    border-top: 1px solid var(--el-border-color-lighter);
  }
}

// 暗黑主题样式
html.dark {
  :deep(.el-dialog) {
    background-color: var(--el-bg-color);
    
    .el-dialog__header {
      border-bottom-color: var(--el-border-color-darker);
    }
    
    .el-dialog__footer {
      border-top-color: var(--el-border-color-darker);
    }
  }
}
</style>
